from flask import request,current_app
from flask_socketio import SocketIO, emit, join_room, leave_room
from utils.randomUtils import generate_random_token, generate_random_by_time
import threading
from .baseGraphNode import  *
from ..execute.baseExeHis import BaseExeHis
from .sessionInfo import SessionInfo

class HttpGraphNode(BaseGraphNode):
    
    def get_socketio_instance(self):
        if self._socketio_instance is None:
            self._socketio_instance = current_app.extensions['socketio']
            
            @self._socketio_instance.on('connect', namespace=self.full_url)
            def on_connect():
                id = request.args.get("id")  # 从连接参数获取
                self.graphNodeManager.sid_to_id[request.sid] = id
                self.graphNodeManager.get_session_info(id, self._socketio_instance, request.sid, self.full_url)
                print(f"WebSocket connected on namespace: {self.full_url} User id:{id} sid:{request.sid}")
                join_room(id)
                emit('response', {'data': 'Connected to WebSocket!'})

            @self._socketio_instance.on('disconnect', namespace=self.full_url)
            def on_disconnect():
                sid = request.sid
                print(f"WebSocket disconnected on namespace: {self.full_url} User sid: {sid}")
                leave_room(self.graphNodeManager.sid_to_id[sid])
                self.graphNodeManager.id_to_sessionInfo.pop(self.graphNodeManager.sid_to_id[sid])

        return self._socketio_instance
    
    def __init__(self, id:str, data:dict, graphNodeManager, random_key:str):
        super().__init__(id, data, graphNodeManager, random_key)
        self.route = data['data']['route']
        self.enWS = data['data'].get('enWS', True)
        self.enInterrupt = data['data'].get('enInterrupt', True)
        self.full_url = '/socket.io/' + generate_random_token(random_key)
        self._ws_token = self.full_url
        self.running = False
        from managers.userManager import ProjectManager
        self._ws_token = None  
        self._socketio_instance = None
        self.get_socketio_instance()
        self.graphNodeManager.http_node = self

    def execute(self, session_info: SessionInfo=None, exe_his: BaseExeHis=None):
        if not self.running:
            if self.route in self.graphNodeManager.project.onlineRoutes:
                self.graphNodeManager.project.onlineRoutes.pop(self.route)
            self.running = True
            
            # 获取全局 SocketIO 实例
            socketio_instance = self.get_socketio_instance()
            route = self.route
            full_url = self.full_url

            @socketio_instance.on(route, namespace=full_url)
            def handle_message(msg):
                if 'data' not in msg:
                    return
                msgdata = msg['data']
                id = msg.get('id', None)
                if id is None:
                    print(f'{self.name} handle_message id is None')
                    return
                
                sessionInfo = self.graphNodeManager.get_session_info(id, socketio_instance, request.sid, self.full_url) 
                with session_info.out_write_lock:
                    if sessionInfo.out.get(self.id,None) is None: sessionInfo.out[self.id] = {}
                    if 'query-msg' not in sessionInfo.out[self.id]: 
                        sessionInfo.out[self.id]['query-msg'] = []
                    sessionInfo.out[self.id]['query-msg'].append(msgdata)
                self.executed_num += 1
                self.flow_next(sessionInfo, type='text', role='user')
            
            if not self.graphNodeManager.project.is_websocket_running:
                self.graphNodeManager.project.addOnlineRoute(self.route, 'message', self.name)
                self.graphNodeManager.project.is_websocket_running = True
                print(f'WebSocket server started and listening on namespace: {self.full_url}')
        else:
            # 返回消息的逻辑
            assert session_info is not None, "session_info should not be None when returning message"
            returnMsg = ''
            if 'return-msg' in self.dict['in']:
                msgFrom = self.dict['in']['return-msg']
                prenode = self.graphNodeManager.nodesByIdDict[msgFrom['nodeId']]
                returnMsg = prenode.get_newest_output_in_session(session_info, msgFrom['handle'])
            session_info.ws.emit('response', {'data': returnMsg}, room=session_info.id, namespace=self.full_url)
        return self.full_url
    
    def stop(self):
        if not self.running:
            return
            
        self.running = False
        self.graphNodeManager.project.removeOnlineRoute(self.route)
        
        # 如果没有其他路由在使用 WebSocket 服务器，则关闭它
        if not self.graphNodeManager.project.onlineRoutes:
            if self._socketio_instance is not None:
                self._socketio_instance.close()
                self._socketio_instance = None
                self.graphNodeManager.project.is_websocket_running = False    
        if self._socketio_instance is not None:
            self._socketio_instance.close()
